package restless.core.managers {
	
	import flash.display.BitmapData;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.FullScreenEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Vector3D;
	import flash.ui.Mouse;
	import flash.ui.MouseCursorData;
	import restless.core.gameObjs.RLEBlitMC;
	import restless.utilities.Benchmark;
	
	import restless.core.RLEScreen;
	import restless.core.gameObjs.RLEManagedObj;
	import restless.core.interfaces.IMouseControled;
	import restless.core.interfaces.IStage;
	
	/**
	 * ...
	 * @author MNS
	 */
	
	public class RLEMouseManager extends RLEManagedObj {
		
		private var vCursorStrings:Vector.<String> = new Vector.<String>;
		private var vCursorGfx:Vector.<Vector.<BitmapData>> = new Vector.<Vector.<BitmapData>>;
		private var vLeftClick:Vector.<IMouseControled> = new Vector.<IMouseControled>;
		private var vRightClick:Vector.<IMouseControled> = new Vector.<IMouseControled>;
		private var vMouseWheel:Vector.<IMouseControled> = new Vector.<IMouseControled>;
		private var vMove:Vector.<IMouseControled> = new Vector.<IMouseControled>;
		private var vScreenList:Vector.<RLEScreen>;
		
		private var cursorData:MouseCursorData;
		private var tempMouseObj:IMouseControled;
		private var tempScreen:RLEScreen;
		private var currentMouseScreen:RLEScreen;
		
		private var _customCursor:Boolean = false;
		private var _click:Boolean = false;
		private var _mouseMove:Boolean = false;
		private var _mouseWheel:Boolean = false;
		private var _mouseOver:Boolean = false;
		private var _mouse:Boolean = false;
		private var _screenMouse:Point = new Point;
		private var _stageMouse:Point = new Point;
		
		private var tempNum:int;
		private var pri:int;
		private var compair:int = -1;
		
		public function RLEMouseManager() {
			setRE();
		}
		
		private function move(e:MouseEvent):void {
			_stageMouse.x = stage.mouseX;
			_stageMouse.y = stage.mouseY;
			
			if (_stageMouse.x > RE.displayWidth) { _stageMouse.x = RE.displayWidth; } 
			else if (_stageMouse.x < 0) { _stageMouse.x = 0; }
			
			if (_stageMouse.y > RE.displayHeight) { _stageMouse.y = RE.displayHeight; } 
			else if (_stageMouse.y < 0) { _stageMouse.y = 0; }
			
			compair = -1;
			
			i = vScreenList.length - 1;
			for (i; i > -1; i--) {
				tempScreen = vScreenList[i];
				if (tempScreen.hitTestPoint(_stageMouse) ) {
					pri = tempScreen.mousePriority;
					if (pri > compair) {
						compair = pri;
						currentMouseScreen = tempScreen;
					}
				}
			}
			
			currentMouseScreen.mOver();
			_screenMouse = currentMouseScreen.screenMouse;
			
			i = vMove.length - 1;
			for (i; i > -1; i--) {
				tempMouseObj = vMove[i];
				tempMouseObj.mMove( _screenMouse );
			}
		}
		
		private function clickLeft(e:Event):void {
			
			i = vLeftClick.length - 1;
			if (i > -1) {
				var clicked:IMouseControled;
				compair = -1;
				for (i; i > -1; i--) {
					tempMouseObj = vLeftClick[i];
					if (!tempMouseObj.clickGlobal) {
						if (tempMouseObj.hitTestPoint(screenMouse)) {
							pri = tempMouseObj.mousePriority;
							if ( pri > compair ) {
								compair = pri;
								clicked = tempMouseObj;
							}
						}
					} else {
						tempMouseObj.mClickL();
					}
				}
				
				if (compair > 0) {
					clicked.mClickL();
				}
			}
		}
		
		private function clickRight(e:MouseEvent = null):void {
			//mark.start();
			
			i = vRightClick.length-1;
			if (i > -1) {
				var clicked:IMouseControled;
				compair = -1;
				for (i; i > -1; i--) {
					tempMouseObj = vRightClick[i];
					if (!tempMouseObj.clickGlobal) {
						if (tempMouseObj.hitTestPoint(screenMouse)) {
							pri = tempMouseObj.mousePriority;
							if ( pri > compair ) {
								compair = pri;
								clicked = tempMouseObj;
							}
						}
					} else {
						tempMouseObj.mClickR();
					}
				}
				
				if (compair > 0) {
					clicked.mClickR();
				}
			}
		}
		
		private function wheel(e:MouseEvent = null):void {
			var numOfObjs:int = vMouseWheel.length;
			//mark.start();
			i = vMouseWheel.length-1;
			if (i > -1) {
				if (e.delta > 0) {
					for (i; i > -1; i--) {
						tempMouseObj = vMouseWheel[i];
						tempMouseObj.mWheelUp();
					}
				} else {
					for (i; i > -1; i--) {
						tempMouseObj = vMouseWheel[i];
						tempMouseObj.mWheelDown();
					}
				}
			}
		}
		
		public function registerScreen(screen:RLEScreen):void {
			tempScreen = screen;
			if (vScreenList.indexOf(tempScreen) > -1 ) { return; }
			vScreenList.push(tempScreen);
		}
		
		public function setScreenList( screens:Vector.<RLEScreen> ):void {
			vScreenList = screens;
		}
		
		public function get screenMouseX():Number {
			return _screenMouse.x;
		}
		
		public function get screenMouseY():Number {
			return _screenMouse.y;
		}
		
		public function get screenMouse():Point {
			return _screenMouse;
		}
		
		public function get stageMouseX():Number {
			return _stageMouse.x;
		}
		
		public function get stageMouseY():Number {
			return _stageMouse.y;
		}
		
		public function get stageMouse():Point {
			return _stageMouse;
		}
		
		public function leftClickList(mouseObj:IMouseControled, add:Boolean):void {
			if (!_click) {
				addClickListeners();
			}
			tempMouseObj = mouseObj;
			
			var num:int = vLeftClick.indexOf(tempMouseObj);
			if (add) {
				if (num < 0) { vLeftClick.push(tempMouseObj); }
			} else {
				if (num >= 0) { vLeftClick.splice(num, 1); }
			}
		}
		
		public function rightClickList(mouseObj:IMouseControled, add:Boolean):void {
			if (!_click) {
				addClickListeners();
			}
			tempMouseObj = mouseObj;
			
			var num:int = vRightClick.indexOf(tempMouseObj);
			if (add) {
				if (num < 0) { vRightClick.push(tempMouseObj); }
			} else {
				if (num >= 0) { vRightClick.splice(num, 1); }
			}
		}
		
		public function mouseOverList(mouseObj:IMouseControled, add:Boolean):void {
			if (!_mouseOver) { 
				addMoveListener();
			}
			tempMouseObj = mouseObj;
			var num:int = vMove.indexOf(tempMouseObj);
			if (add) { 
				if ( num < 0) { vMove.push(tempMouseObj); }
			} else {
				if (num >= 0) { vMove.splice(num, 1); }
			}
		}
		
		public function mouseWheelList(mouseObj:IMouseControled, add:Boolean):void {
			if (!_mouseWheel) { 
				addWheelListener();
			}
			tempMouseObj = mouseObj;
			var num:int = vMouseWheel.indexOf(tempMouseObj);
			if (add) { 
				if ( num < 0) { vMouseWheel.push(tempMouseObj); }
			} else {
				if (num >= 0) { vMouseWheel.splice(num, 1); }
			}
		}
		
		public function addWheelListener():void {
			if (!_mouseWheel) {
				stage.addEventListener(MouseEvent.MOUSE_WHEEL, wheel, false, 0, true);
				_mouseWheel = true;
			}
		}
		
		public function addClickListeners():void {
			if (!_click) {
				stage.addEventListener(MouseEvent.RIGHT_CLICK, clickRight, false, 0, true);
				stage.addEventListener(MouseEvent.CLICK, clickLeft, false, 0, true);
				_click = true;
			}
		}
		
		public function addMoveListener():void {
			if (!_mouseMove) {
				stage.addEventListener(MouseEvent.MOUSE_MOVE, move, false, 0, true);
				_mouseMove = true;
			}
		}
		
		public function addCursorAnimation(id:String, animation:Vector.<BitmapData>):void {
			if (Mouse.supportsNativeCursor) {
				var num:int = vCursorStrings.indexOf(id);
				if (num < 0) {
					vCursorStrings.push(id);
					vCursorGfx.push(animation);
				}
			}
		}
		
		public function switchCursor(id:String, play:Boolean, frameRate:int):void {
			if (Mouse.supportsNativeCursor) {
				if (_customCursor = false) {
					_customCursor = true;
					cursorData = new MouseCursorData();
				}
				var num:int = vCursorStrings.indexOf(id);
				cursorData.data = vCursorGfx[num];
				Mouse.registerCursor(id, cursorData);
			}
		}
		
		public function removeCursor():void {
			if (_customCursor) {
				_customCursor = false;
				Mouse.unregisterCursor(Mouse.cursor);
			}
		}
		
		public function removeListeners():void {
			if (_click) {
				stage.removeEventListener(MouseEvent.RIGHT_CLICK, clickRight);
				stage.removeEventListener(MouseEvent.CLICK, clickLeft);
				_click = false;
			}
			
			if (_mouseMove) {
				stage.removeEventListener(MouseEvent.MOUSE_MOVE, move);
				_mouseMove = false;
			}
			
			if (_mouseWheel) {
				stage.removeEventListener(MouseEvent.MOUSE_WHEEL, wheel);
				_mouseWheel = false;
			}
		}
		
		public override function dispose():void {
			removeListeners();
			vCursorStrings = null;
			vCursorGfx = null;
			vScreenList = null;
			vLeftClick = null;
			vRightClick = null;
			vMove = null;
			cursorData = null;
			tempMouseObj = null;
			super.dispose();
		}
	}
}